/**
 * @file DatabaseManager.h
 * @brief 数据库管理器和查询结果处理相关类的定义
 * @details 提供数据库连接管理、查询执行、事务处理和结果集处理等功能
 */

#pragma once

#include "ConnectionPool.h"
#include "QueryBuilder.h"
#include "Transaction.h"
#include "DatabaseError.h"
#include "ORM.h"
#include "../Utils/Utils.h"
#include <Poco/Data/RecordSet.h>
#include <future>
#include <functional>
#include <memory>
#include <vector>
#include <map>
#include <optional>

namespace CLink 
{
namespace Db 
{
struct FieldDefinition;

/**
 * @brief 查询结果集类
 * @details 封装数据库查询结果，提供访问和转换结果数据的方法
 */
class CLINK_CLASS ResultSet {
public:
    /**
     * @brief 构造函数
     * @param recordSet Poco库的记录集对象
     */
    explicit ResultSet(Poco::Data::RecordSet recordSet) 
        : _recordSet(std::move(recordSet)) {}

    /**
     * @brief 获取结果集中的行数
     * @return 行数
     */
    size_t rowCount() const { return _recordSet.rowCount(); }
    
    /**
     * @brief 获取结果集中的列数
     * @return 列数
     */
    size_t columnCount() const { return _recordSet.columnCount(); }
    
    /**
     * @brief 获取所有列的名称
     * @return 包含所有列名的字符串向量
     */
    std::vector<std::string> getColumnNames() const {
        std::vector<std::string> names;
        for (size_t i = 0; i < columnCount(); ++i) {
            names.push_back(_recordSet.columnName(i));
        }
        return names;
    }
    
    /**
     * @brief 将结果集转换为键值对映射数组
     * @details 每行数据转换为一个map，键为列名，值为字符串形式的数据
     * @return 包含所有行数据的map数组
     */
    std::vector<std::map<std::string, std::string>> toMap() {
        std::vector<std::map<std::string, std::string>> result;
        auto columns = getColumnNames();
        
        if( rowCount() == 0)
        {
            return result;  // 如果没有数据，直接返回空结果
		}

        do {
            std::map<std::string, std::string> row;
            for (size_t i = 0; i < columns.size(); ++i) {
				auto value = _recordSet.value(i);
                row[columns[i]] = value.isEmpty() ? "" : value.convert<std::string>();
            }
            result.push_back(row);
        } while (_recordSet.moveNext());
        
        return result;
    }

private:
    Poco::Data::RecordSet _recordSet;  ///< Poco库的记录集对象
};

/**
 * @brief 异步查询结果封装类
 * @details 封装异步操作的结果，提供检查完成状态和获取结果的方法
 * @tparam T 异步操作返回的结果类型
 */
template<typename T>
class AsyncResult {
public:
    /**
     * @brief 构造函数
     * @param future 包含异步操作结果的future对象
     */
    explicit AsyncResult(std::future<T> future) 
        : _future(std::move(future)) {}
    
    /**
     * @brief 检查异步操作是否已完成
     * @return 如果操作已完成返回true，否则返回false
     */
    bool isReady() const {
        return _future.wait_for(std::chrono::seconds(0)) == std::future_status::ready;
    }
    
    /**
     * @brief 获取异步操作的结果（阻塞等待直到完成）
     * @return 异步操作的结果
     * @throws 如果异步操作抛出异常，则该异常会被重新抛出
     */
    T get() { return _future.get(); }
    
    /**
     * @brief 带超时的等待异步操作结果
     * @param timeout 等待超时时间
     * @return 如果在超时时间内完成，返回操作结果；否则返回std::nullopt
     */
    std::optional<T> wait_for(const std::chrono::milliseconds& timeout) {
        if (_future.wait_for(timeout) == std::future_status::ready) {
            return _future.get();
        }
        return std::nullopt;
    }

private:
    std::future<T> _future;  ///< 包含异步操作结果的future对象
};

/**
 * @brief 数据库管理器类
 * @details 提供数据库连接管理、SQL查询执行、事务处理等核心功能，
 *          采用单例模式设计，确保全局只有一个数据库管理实例
 */
class CLINK_CLASS DatabaseManager
{
public:
    /** @brief 数据库管理器智能指针类型 */
    using Ptr = std::shared_ptr<DatabaseManager>;
    
    /**
     * @brief 初始化数据库连接池
     * @param config 连接池配置信息
     * @throws DatabaseError 如果初始化失败
     */
    void initialize(const ConnectionConfig& config);
    
    /**
     * @brief 关闭数据库连接池并释放资源
     */
    void shutdown();
    
    /**
     * @brief 获取SQL查询构建器实例
     * @return 查询构建器对象
     */
    QueryBuilder getQueryBuilder();
    
    /**
     * @brief 执行SQL查询语句
     * @param sql SQL查询语句
     * @return 查询结果集
     * @throws DatabaseError 如果查询执行失败
     */
    ResultSet query(const std::string& sql);
    
    /**
     * @brief 执行查询构建器生成的查询
     * @param builder 查询构建器对象
     * @return 查询结果集
     * @throws DatabaseError 如果查询执行失败
     */
    ResultSet query(const QueryBuilder& builder);
    
    /**
     * @brief 执行非查询SQL语句（如INSERT、UPDATE、DELETE等）
     * @param sql SQL语句
     * @return 受影响的行数
     * @throws DatabaseError 如果执行失败
     */
    size_t execute(const std::string& sql);
    
    /**
     * @brief 执行查询构建器生成的非查询SQL语句
     * @param builder 查询构建器对象
     * @return 受影响的行数
     * @throws DatabaseError 如果执行失败
     */
    size_t execute(const QueryBuilder& builder);
    
    /**
     * @brief 异步执行SQL查询语句
     * @param sql SQL查询语句
     * @return 异步查询结果对象
     */
    AsyncResult<ResultSet> queryAsync(const std::string& sql);
    
    /**
     * @brief 异步执行查询构建器生成的查询
     * @param builder 查询构建器对象
     * @return 异步查询结果对象
     */
    AsyncResult<ResultSet> queryAsync(const QueryBuilder& builder);
    
    /**
     * @brief 异步执行非查询SQL语句
     * @param sql SQL语句
     * @return 异步执行结果对象，包含受影响的行数
     */
    AsyncResult<size_t> executeAsync(const std::string& sql);
    
    /**
     * @brief 异步执行查询构建器生成的非查询SQL语句
     * @param builder 查询构建器对象
     * @return 异步执行结果对象，包含受影响的行数
     */
    AsyncResult<size_t> executeAsync(const QueryBuilder& builder);
    
    /**
     * @brief 开始一个新的数据库事务
     * @param level 事务隔离级别
     * @return 事务对象
     * @throws DatabaseError 如果事务创建失败
     */
    Transaction beginTransaction(IsolationLevel level = IsolationLevel::REPEATABLE_READ);
    
    /**
     * @brief 执行批量操作
     * @details 使用预处理语句批量执行相同的SQL语句，提高性能
     * @tparam Container 参数容器类型
     * @param sql 预处理SQL语句
     * @param params 参数容器，包含多组参数
     * @throws DatabaseError 如果批量操作执行失败
     */
    template<typename Container>
    void batch(const std::string& sql, const Container& params);
    
    /**
     * @brief 获取最后插入记录的ID
     * @return 最后插入记录的ID
     * @throws DatabaseError 如果获取失败
     */
    int64_t lastInsertId();
    
    /**
     * @brief 获取最近一次操作影响的行数
     * @return 受影响的行数
     */
    size_t affectedRows();
    
    /**
     * @brief 检查数据库中是否存在指定表
     * @param tableName 表名
     * @return 如果表存在返回true，否则返回false
     */
    bool tableExists(const std::string& tableName);
    
    /**
     * @brief 获取表的结构信息
     * @param tableName 表名
     * @return 表字段定义的向量
     * @throws DatabaseError 如果获取表结构失败
     */
    std::vector<FieldDefinition> getTableSchema(const std::string& tableName);
    
    /**
     * @brief 转义SQL字符串，防止SQL注入
     * @param str 需要转义的字符串
     * @return 转义后的安全字符串
     */
    std::string escape(const std::string& str);

    /** @brief 默认构造函数（受保护，仅供单例模式使用） */
    DatabaseManager() = default;
    
private:
    std::unique_ptr<ConnectionPool> _pool;  ///< 数据库连接池
    std::string _last_insert;
    
    /**
     * @brief 使用连接池中的连接执行回调函数
     * @tparam T 回调函数返回类型
     * @param callback 需要执行的回调函数
     * @return 回调函数的返回值
     * @throws DatabaseError 如果执行过程中发生错误
     */
    template<typename T>
    T executeWithConnection(std::function<T(Connection&)> callback);
    
    /**
     * @brief 异步使用连接池中的连接执行回调函数
     * @tparam T 回调函数返回类型
     * @param callback 需要执行的回调函数
     * @return 异步结果对象
     */
    template<typename T>
    AsyncResult<T> executeAsyncWithConnection(std::function<T(Connection&)> callback);
};

/**
 * @brief 查询结果处理器类
 * @details 提供高级查询结果处理功能，包括回调处理、分页处理和流式处理
 */
class QueryProcessor {
public:
    /**
     * @brief 构造函数
     * @param manager 数据库管理器智能指针
     */
    explicit QueryProcessor(DatabaseManager::Ptr manager)
        : _manager(manager) {}
    
    /**
     * @brief 执行查询并通过回调处理结果
     * @tparam Callback 回调函数类型
     * @param builder 查询构建器对象
     * @param callback 处理结果的回调函数
     * @throws DatabaseError 如果查询执行失败
     */
    template<typename Callback>
    void process(const QueryBuilder& builder, Callback callback) {
        auto result = _manager->query(builder);
        callback(result);
    }
    
    /**
     * @brief 分页处理查询结果
     * @details 自动分页查询数据，每次查询一页并通过回调处理
     * @tparam Callback 回调函数类型
     * @param builder 查询构建器对象
     * @param pageSize 每页记录数
     * @param callback 处理每页结果的回调函数
     * @throws DatabaseError 如果查询执行失败
     */
    template<typename Callback>
    void processByPage(QueryBuilder& builder, 
                      size_t pageSize, 
                      Callback callback) {
        size_t page = 1;
        while (true) {
            auto result = _manager->query(builder.page(page, pageSize));
            if (result.rowCount() == 0) {
                break;
            }
            callback(result);
            ++page;
        }
    }
    
    /**
     * @brief 流式处理查询结果
     * @details 逐行处理查询结果，通过回调函数处理每一行数据
     * @tparam Callback 回调函数类型，接收map<string,string>参数，返回bool值
     * @param builder 查询构建器对象
     * @param callback 处理每行数据的回调函数，返回false时停止处理
     * @throws DatabaseError 如果查询执行失败
     */
    template<typename Callback>
    void processAsStream(const QueryBuilder& builder, Callback callback) {
        auto result = _manager->query(builder);
        auto columns = result.getColumnNames();
        
        while (!result._recordSet.moveNext()) {
            std::map<std::string, std::string> row;
            for (size_t i = 0; i < columns.size(); ++i) {
                row[columns[i]] = result._recordSet.value(i).convert<std::string>();
            }
            if (!callback(row)) {
                break;
            }
        }
    }

private:
    DatabaseManager::Ptr _manager;  ///< 数据库管理器智能指针
};

} // namespace db
} // namespace CLink